﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Newtonsoft.Json;

namespace POC.Controls
{
    public class DeviceThumb : Thumb, ISelectable
    {
        public DeviceThumb()
        {
            this.X = this.Y = 5;
            this.PreviewMouseLeftButtonUp += DeviceThumb_PreviewMouseLeftButtonUp;
            this.DragDelta += DeviceThumb_DragDelta;
        }

        private void DeviceThumb_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (!this.IsDraged)
                this.IsSelected = !this.IsSelected;
            this.IsDraged = false;
        }

        public int X { get { return (int)Canvas.GetLeft(this); } set { Canvas.SetLeft(this, value); } }
        public int Y { get { return (int)Canvas.GetTop(this); } set { Canvas.SetTop(this, value); } }
        public string DeviceIp
        {
            get { return (string)GetValue(DeviceIpProperty); }
            set { SetValue(DeviceIpProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DeviceIp.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DeviceIpProperty =
            DependencyProperty.Register("DeviceIp", typeof(string), typeof(DeviceThumb));

        public string DeviceMac
        {
            get { return (string)GetValue(DeviceMacProperty); }
            set { SetValue(DeviceMacProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DeviceMac.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DeviceMacProperty =
            DependencyProperty.Register("DeviceMac", typeof(string), typeof(DeviceThumb));


        public string ClientVersion
        {
            get { return (string)GetValue(ClientVersionProperty); }
            set { SetValue(ClientVersionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ClientVersion.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ClientVersionProperty =
            DependencyProperty.Register("ClientVersion", typeof(string), typeof(DeviceThumb));


        public string SessionID { get; set; }

        public bool IsOnLine
        {
            get { return (bool)GetValue(IsOnLineProperty); }
            set { SetValue(IsOnLineProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsOnLine.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsOnLineProperty =
            DependencyProperty.Register("IsOnLine", typeof(bool), typeof(DeviceThumb));


        public string DeviceName
        {
            get { return (string)GetValue(DeviceNameProperty); }
            set { SetValue(DeviceNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DeviceName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DeviceNameProperty =
            DependencyProperty.Register("DeviceName", typeof(string), typeof(DeviceThumb));

        public bool IsSelected
        {
            get { return (bool)GetValue(IsSelectedProperty); }
            set { SetValue(IsSelectedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsSelected.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsSelectedProperty =
            DependencyProperty.Register("IsSelected", typeof(bool), typeof(DeviceThumb), new PropertyMetadata(false));

        private bool _Updating;
        public bool Updating
        {
            get { return _Updating; }
            set
            {
                _Updating = value;
            }
        }

        public int Speed
        {
            get { return (int)GetValue(SpeedProperty); }
            set { SetValue(SpeedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Speed.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SpeedProperty =
            DependencyProperty.Register("Speed", typeof(int), typeof(DeviceThumb), new PropertyMetadata(0));


        public int Maximum
        {
            get { return (int)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Maximum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(int), typeof(DeviceThumb), new PropertyMetadata(100));


        public ImageSource ImageSource
        {
            get { return (ImageSource)GetValue(ImageSourceProperty); }
            set { SetValue(ImageSourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ImageSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImageSourceProperty =
            DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(DeviceThumb));

        public bool IsDraged { get; set; }
        private void DeviceThumb_DragDelta(object sender, DragDeltaEventArgs e)
        {
            this.IsDraged = true;
            DesignerCanvas designerCanvas = VisualTreeHelper.GetParent(this) as DesignerCanvas;

            var devices = this.IsSelected ? designerCanvas.Children.OfType<DeviceThumb>().Where(p => p.IsSelected) : new DeviceThumb[] { this };
            this.DragDeltaMethod(e, devices.ToArray());
            designerCanvas.InvalidateMeasure();
            e.Handled = true;
            //this.Margin = new Thickness(this.Margin.Left + e.HorizontalChange, this.Margin.Top + e.VerticalChange, 0, 0);
        }

        private void DragDeltaMethod(DragDeltaEventArgs e, params DeviceThumb[] devices)
        {
            double minLeft = double.MaxValue;
            double minTop = double.MaxValue;

            // we only move DesignerItems
            foreach (var item in devices)
            {
                double left = Canvas.GetLeft(item);
                double top = Canvas.GetTop(item);

                minLeft = double.IsNaN(left) ? 0 : Math.Min(left, minLeft);
                minTop = double.IsNaN(top) ? 0 : Math.Min(top, minTop);
            }

            double deltaHorizontal = Math.Max(-minLeft, e.HorizontalChange);
            double deltaVertical = Math.Max(-minTop, e.VerticalChange);

            foreach (var item in devices)
            {
                double left = Canvas.GetLeft(item);
                double top = Canvas.GetTop(item);

                if (double.IsNaN(left)) left = 0;
                if (double.IsNaN(top)) top = 0;

                Canvas.SetLeft(item, left + deltaHorizontal);
                Canvas.SetTop(item, top + deltaVertical);
            }
        }

        public DeviceType DeviceType
        {
            get { return (DeviceType)GetValue(DeviceTypeProperty); }
            set { SetValue(DeviceTypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DeviceType.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DeviceTypeProperty =
            DependencyProperty.Register("DeviceType", typeof(DeviceType), typeof(DeviceThumb), new PropertyMetadata(DeviceType.WorkStation));


        public DeviceThumb Clone()
        {
            return new DeviceThumb()
            {
                DeviceIp = this.DeviceIp,
                DeviceMac = this.DeviceMac,
                DeviceName = this.DeviceName,
                DeviceType = this.DeviceType,
                ClientVersion = this.ClientVersion,
            };
            //return (DeviceThumb)MemberwiseClone();
        }

        public void Copy(DeviceThumb dev)
        {
            DeviceIp = dev.DeviceIp;
            DeviceMac = dev.DeviceMac;
            DeviceName = dev.DeviceName;
            DeviceType = dev.DeviceType;
            ClientVersion = dev.ClientVersion;
        }
    }

    public enum DeviceType
    {
        WorkStation,
        Server
    }
}
